/*
 *   Copyright (c) 2010-2022, SIUFUNG
 */
package net.siufung.market.base.tenant.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.siufung.core.model.enums.DeletedEnum;
import net.siufung.core.page.PagerResult;
import net.siufung.core.result.Result;
import net.siufung.core.result.ResultFail;
import net.siufung.core.result.ResultOk;
import net.siufung.core.utils.CopyUtil;
import net.siufung.market.base.tenant.api.ITenantUserApi;
import net.siufung.market.base.tenant.controller.assembler.TenantAssembler;
import net.siufung.market.base.tenant.controller.model.dto.TenantDto;
import net.siufung.market.base.tenant.controller.model.dto.TenantSaveDto;
import net.siufung.market.base.tenant.controller.model.dto.TenantUpdateDto;
import net.siufung.market.base.tenant.controller.model.dto.page.TenantPageDto;
import net.siufung.market.base.tenant.controller.model.vo.TenantVo;
import net.siufung.market.base.tenant.controller.regulation.TenantCreateRegulation;
import net.siufung.market.base.tenant.controller.regulation.TenantDeleteRegulation;
import net.siufung.market.base.tenant.controller.regulation.TenantStatusRegulation;
import net.siufung.market.base.tenant.controller.regulation.TenantUpdateRegulation;
import net.siufung.market.base.tenant.mapper.ITenantMapper;
import net.siufung.market.base.tenant.mapper.ITenantProfileMapper;
import net.siufung.market.base.tenant.mapper.entity.Tenant;
import net.siufung.market.base.tenant.mapper.entity.TenantProfile;
import net.siufung.market.base.tenant.service.ITenantService;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 系统租户表 前端控制器
 *
 * @author 陈建峰
 * @since 2022-07-06 14:45:08
 */
@Api(tags = "租户管理")
@Slf4j
@AllArgsConstructor
@RestController
@RequestMapping("/sys/tenant")
public class TenantController {

    private final ITenantMapper tenantMapper;
    private final ITenantService tenantService;
    private final ITenantProfileMapper tenantProfileMapper;
    private final ITenantUserApi tenantUserApi;

    /**
     * 通过主键获取 系统租户表
     * @param id 主键
     * @return Result<TenantVo>
     * */
    @ApiOperation(value = "通过Id获取系统租户信息")
    @GetMapping(value = "/id/{id}")
    public Result<TenantVo> getById(
            @PathVariable("id") Integer id) {
        return Result.ok(
            TenantAssembler.from(
                    tenantMapper.selectById(id),
                    tenantProfileMapper.selectById(id)));
    }

    /**
     * 获取 系统租户表列表
     * @param tenantDto 属性
     * @return Result<List<TenantVo>>
     * */
    @ApiOperation(value = "获取系统租户表列表")
    @PostMapping(value = "/list")
    public Result<List<TenantVo>> list(
            @RequestBody TenantDto tenantDto) {
        List<Tenant> tenantList = tenantMapper.selectList(Wrappers.query(tenantDto.to()));
        List<Integer> tenantIdList = tenantList.stream()
                .map(Tenant::getId).collect(Collectors.toList());
        List<TenantProfile> tenantProfileList = Lists.newArrayList();
        if(!CollectionUtils.isEmpty(tenantIdList)){
            tenantProfileList = tenantProfileMapper.selectBatchIds(tenantIdList);
        }
        return Result.ok(
            TenantAssembler.fromList(tenantList, tenantProfileList));
    }

    /**
     * 获取 系统租户表分页
     * @param tenantPageDto 属性
     * @return 查询分页结果
     * */
    @ApiOperation(value = "获取系统租户表分页")
    @PostMapping(value="/page")
    public Result<PagerResult<TenantVo>> getPage(
            @RequestBody TenantPageDto tenantPageDto) {
        tenantPageDto.validated();
        QueryWrapper<Tenant> wrapper = new QueryWrapper<>();
        wrapper.lambda().like(!Strings.isNullOrEmpty(tenantPageDto.getName()) ,
                Tenant::getName, tenantPageDto.getName());
        wrapper.lambda().eq(Objects.nonNull(tenantPageDto.getTenantTypeId()) ,
                Tenant::getTenantTypeId, tenantPageDto.getTenantTypeId());
        wrapper.lambda().orderByDesc(Tenant::getId);
        IPage<Tenant> tenantPage = tenantMapper.selectPage(
                new Page<>(tenantPageDto.getPageNo(), tenantPageDto.getPageSize()), wrapper);
        PagerResult<TenantVo> tenantVoPage = new PagerResult<>(
                tenantPage.getCurrent(), tenantPage.getSize(), tenantPage.getTotal());
        List<Tenant> tenantList = tenantPage.getRecords();
        List<Integer> tenantIdList = tenantList.stream()
                .map(Tenant::getId).collect(Collectors.toList());
        List<TenantProfile> tenantProfileList = Lists.newArrayList();
        if(!CollectionUtils.isEmpty(tenantIdList)){
            tenantProfileList = tenantProfileMapper.selectBatchIds(tenantIdList);
        }
        tenantVoPage.setRecords(
            TenantAssembler.fromList(tenantList, tenantProfileList));
        return Result.ok(tenantVoPage);
    }

    /**
     * 通过主键删除 系统租户表 对象
     * @param id 主键
     * @return 删除结果
     * */
    @ApiOperation(value = "删除系统租户表对象")
    @PostMapping(value="/remove/{id}")
    public Result<Void> deleteById(
        @PathVariable("id") Integer id) {
        TenantDeleteRegulation tenantDeleteRegulation = new TenantDeleteRegulation(tenantMapper);
        tenantDeleteRegulation.isSatisfiedBy(id);
        if(tenantService.removeById(id)){
            return Result.ok(ResultOk.REMOVE);
        }
        return Result.fail(ResultFail.DATA_REMOVE_ERROR);
    }

    /**
     * 创建 系统租户表
     * @param tenantSaveDto 对象属性
     * @return 创建结果
     * */
    @ApiOperation(value = "创建 系统租户表")
    @PostMapping(value="/create")
    public Result<Void> create(
            @RequestBody TenantSaveDto tenantSaveDto) {
        tenantSaveDto.validated();
        Tenant tenant = tenantSaveDto.to();
        TenantProfile tenantProfile = tenantSaveDto.toProfile();
        TenantCreateRegulation tenantCreateRegulation =
                new TenantCreateRegulation(tenantMapper, tenantProfileMapper, tenantUserApi);
        tenantCreateRegulation.isSatisfiedBy(tenantSaveDto);
        if(tenantService.save(tenant, tenantProfile)){
            return Result.ok(ResultOk.ADD);
        }
        return Result.fail(ResultFail.DATA_ADD_ERROR);
    }

    /**
     * 更新 系统租户表
     * @param tenantUpdateDto 对象属性
     * @return Result<Void>
     * */
    @ApiOperation(value = "更新 系统租户表 信息")
    @PostMapping(value="/update")
    public Result<Void> updateById(
            @RequestBody TenantUpdateDto tenantUpdateDto) {
        tenantUpdateDto.validated();
        Tenant tenantOf = tenantService.getById(tenantUpdateDto.getId());
        CopyUtil.copyPropertiesIgnoreNull(tenantUpdateDto.to(), tenantOf);
        TenantUpdateRegulation tenantUpdateRegulation =
                new TenantUpdateRegulation(tenantMapper, tenantProfileMapper);
        tenantUpdateRegulation.isSatisfiedBy(tenantUpdateDto);
        if(tenantService.updateById(tenantOf, tenantUpdateDto.toProfile())){
            return Result.ok(ResultOk.UPDATE);
        }
        return Result.fail(ResultFail.DATA_UPDATE_ERROR);
    }

    /**
     * 更新 系统租户表 状态
     * @param id 主键
     * @param deleted 数据状态
     * @return Result<Void>
     * */
    @ApiOperation(value = "更新 系统租户表 状态")
    @PostMapping(value="/status/{id}/{deleted}")
    public Result<Void> updateStatusById(
            @PathVariable("id") Integer id,
            @PathVariable("deleted") boolean deleted) {
        TenantStatusRegulation tenantStatusRegulation = new TenantStatusRegulation(tenantMapper);
        tenantStatusRegulation.isSatisfiedBy(id);
        if(tenantService.updateStatusById(id, DeletedEnum.get(deleted))){
            return Result.ok(ResultOk.STATUS);
        }
        return Result.fail(ResultFail.DATA_UPDATE_ERROR);
    }

}